package cn.iocoder.yudao.module.reading.service.community;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.reading.controller.app.community.vo.common.LikeToggleRespVO;
import cn.iocoder.yudao.module.reading.util.CommunityPermissionUtils;
import cn.iocoder.yudao.module.reading.util.CommunityValidationUtils;
import cn.iocoder.yudao.module.reading.controller.app.community.vo.post.PostCreateReqVO;
import cn.iocoder.yudao.module.reading.controller.app.community.vo.post.PostPageReqVO;
import cn.iocoder.yudao.module.reading.controller.app.community.vo.post.PostRespVO;
import cn.iocoder.yudao.module.reading.controller.app.community.vo.post.PostUpdateReqVO;
import cn.iocoder.yudao.module.reading.convert.community.CommunityPostConvert;
import cn.iocoder.yudao.module.reading.dal.dataobject.community.CommunityPostDO;
import cn.iocoder.yudao.module.reading.dal.dataobject.community.CommunityPostLikeDO;
import cn.iocoder.yudao.module.reading.dal.mysql.community.CommunityPostLikeMapper;
import cn.iocoder.yudao.module.reading.dal.mysql.community.CommunityPostMapper;
import cn.iocoder.yudao.module.reading.dal.dataobject.user.UserDO;
import cn.iocoder.yudao.module.reading.service.user.UserService;
import cn.iocoder.yudao.module.reading.framework.util.StaticResourceUrlUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.reading.enums.ErrorCodeConstants.*;

/**
 * 社区帖子服务实现类
 *
 * @author 芋道源码
 */
@Service
@Slf4j
public class CommunityPostServiceImpl implements CommunityPostService {

    @Resource(name = "communityPostMapper")
    private CommunityPostMapper postMapper;

    @Resource
    private CommunityPostLikeMapper postLikeMapper;

    @Resource
    private UserService userService;

    @Resource
    private WxContentSecurityService contentSecurityService;

    @Resource
    private CommunityLimitService limitService;

    @Resource
    private CommunityCountCacheService countCacheService;

    @Resource
    private StaticResourceUrlUtils staticResourceUrlUtils;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createPost(PostCreateReqVO createReqVO, Long userId) {
        // 1. 参数校验
        CommunityValidationUtils.validatePostContentAndImages(createReqVO.getContent(), createReqVO.getImages());
        CommunityValidationUtils.validatePostType(createReqVO.getType());

        // 2. 检查发帖频控
        var limitResult = limitService.checkPostLimit(userId);
        if (!limitResult.getCanOperate()) {
            throw exception(COMMUNITY_POST_LIMIT_EXCEEDED);
        }

        // 3. 内容安全检查（只在有内容时检查）
        if (StrUtil.isNotBlank(createReqVO.getContent())) {
            var sensitiveResult = contentSecurityService.checkTextContent(createReqVO.getContent());
            if (sensitiveResult.getHasSensitive()) {
                throw exception(COMMUNITY_CONTENT_CONTAINS_SENSITIVE);
            }
        }

        // 3. 转换并保存帖子
        CommunityPostDO post = CommunityPostConvert.INSTANCE.convert(createReqVO);
        post.setUserId(userId);

        // 处理图片JSON
        if (CollUtil.isNotEmpty(createReqVO.getImages())) {
            post.setImages(CommunityPostConvert.INSTANCE.convertImagesToJson(createReqVO.getImages()));
        }

        postMapper.insert(post);

        // 4. 记录发帖操作（用于频控）
        limitService.recordPostAction(userId);

        return post.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePost(PostUpdateReqVO updateReqVO, Long userId) {
        // 1. 参数校验
        CommunityValidationUtils.validateId(updateReqVO.getId(), "帖子ID");
        CommunityValidationUtils.validatePostContent(updateReqVO.getContent());
        CommunityValidationUtils.validateImageList(updateReqVO.getImages(), 3);

        // 2. 校验帖子存在和权限
        CommunityPostDO post = validatePostExists(updateReqVO.getId());
        CommunityPermissionUtils.validatePostPermission(post, userId);

        // 3. 内容安全检查
        var sensitiveResult = contentSecurityService.checkTextContent(updateReqVO.getContent());
        if (sensitiveResult.getHasSensitive()) {
            throw exception(COMMUNITY_CONTENT_CONTAINS_SENSITIVE);
        }

        // 4. 更新帖子
        CommunityPostDO updateObj = CommunityPostConvert.INSTANCE.convert(updateReqVO);
        
        // 处理图片JSON
        if (CollUtil.isNotEmpty(updateReqVO.getImages())) {
            updateObj.setImages(CommunityPostConvert.INSTANCE.convertImagesToJson(updateReqVO.getImages()));
        }
        
        postMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePost(Long id, Long userId) {
        // 1. 参数校验
        CommunityValidationUtils.validateId(id, "帖子ID");

        // 2. 校验帖子存在和权限
        CommunityPostDO post = validatePostExists(id);
        CommunityPermissionUtils.validatePostPermission(post, userId);

        // 3. 删除帖子（逻辑删除）
        postMapper.deleteById(id);
    }

    @Override
    public PostRespVO getPost(Long id, Long userId) {
        // 1. 获取帖子信息
        CommunityPostDO post = validatePostExists(id);

        // 2. 增加浏览数
        incrementViewCount(id);

        // 3. 获取用户信息
        UserDO user = userService.getUser(post.getUserId());

        // 4. 获取点赞状态
        Boolean isLiked = false;
        if (userId != null) {
            CommunityPostLikeDO like = postLikeMapper.selectByPostIdAndUserId(id, userId);
            isLiked = like != null;
        }

        // 5. 获取最新的计数数据（优先从缓存获取）
        Long likeCount = countCacheService.getPostLikeCount(id);
        Long commentCount = countCacheService.getPostCommentCount(id);

        // 6. 更新帖子对象的计数字段
        post.setLikeCount(likeCount.intValue());
        post.setCommentCount(commentCount.intValue());

        // 7. 转换返回（带URL转换）
        return CommunityPostConvert.INSTANCE.convert(post, user, isLiked, staticResourceUrlUtils);
    }

    @Override
    public PageResult<PostRespVO> getPostPage(PostPageReqVO pageReqVO, Long userId) {
        // 1. 分页查询帖子
        PageResult<CommunityPostDO> pageResult = postMapper.selectPage(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return PageResult.empty();
        }

        // 2. 获取用户信息
        List<Long> userIds = pageResult.getList().stream()
                .map(CommunityPostDO::getUserId)
                .distinct()
                .collect(Collectors.toList());
        List<UserDO> users = userService.getUserList(userIds);
        Map<Long, UserDO> userMap = users.stream()
                .collect(Collectors.toMap(UserDO::getId, user -> user));

        // 3. 获取点赞状态
        final List<Boolean> likedList;
        if (userId != null) {
            List<Long> postIds = pageResult.getList().stream()
                    .map(CommunityPostDO::getId)
                    .collect(Collectors.toList());
            List<CommunityPostLikeDO> likes = postLikeMapper.selectByPostIdsAndUserId(postIds, userId);
            Map<Long, Boolean> likeMap = likes.stream()
                    .collect(Collectors.toMap(CommunityPostLikeDO::getPostId, like -> true));

            likedList = postIds.stream()
                    .map(postId -> likeMap.getOrDefault(postId, false))
                    .collect(Collectors.toList());
        } else {
            likedList = null;
        }

        // 4. 获取最新的计数数据（优先从缓存获取）
        List<Long> postIds = pageResult.getList().stream()
                .map(CommunityPostDO::getId)
                .collect(Collectors.toList());

        // 批量获取点赞数和评论数
        Map<Long, Long> likeCountMap = new HashMap<>();
        Map<Long, Long> commentCountMap = new HashMap<>();

        for (Long postId : postIds) {
            likeCountMap.put(postId, countCacheService.getPostLikeCount(postId));
            commentCountMap.put(postId, countCacheService.getPostCommentCount(postId));
        }

        // 更新帖子对象的计数字段
        pageResult.getList().forEach(post -> {
            Long likeCount = likeCountMap.get(post.getId());
            Long commentCount = commentCountMap.get(post.getId());
            if (likeCount != null) {
                post.setLikeCount(likeCount.intValue());
            }
            if (commentCount != null) {
                post.setCommentCount(commentCount.intValue());
            }
        });

        // 5. 转换返回（带URL转换）
        final List<CommunityPostDO> postDOList = pageResult.getList();
        List<PostRespVO> postList = postDOList.stream()
                .map(post -> {
                    UserDO user = userMap.get(post.getUserId());
                    Boolean isLiked = likedList != null ?
                            likedList.get(postDOList.indexOf(post)) : false;
                    return CommunityPostConvert.INSTANCE.convert(post, user, isLiked, staticResourceUrlUtils);
                })
                .collect(Collectors.toList());

        return new PageResult<>(postList, pageResult.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LikeToggleRespVO togglePostLike(Long postId, Long userId) {
        // 1. 参数校验
        CommunityValidationUtils.validateId(postId, "帖子ID");

        // 2. 校验帖子存在
        CommunityPostDO post = validatePostExists(postId);

        // 3. 先查询当前点赞状态
        CommunityPostLikeDO existingLike = postLikeMapper.selectByPostIdAndUserId(postId, userId);

        boolean isLiked;
        int likeCountIncrement;

        if (existingLike != null) {
            // 已点赞，取消点赞（使用物理删除）
            postLikeMapper.deleteByPostIdAndUserId(postId, userId);
            isLiked = false;
            likeCountIncrement = -1;
        } else {
            // 未点赞，添加点赞
            CommunityPostLikeDO like = CommunityPostLikeDO.builder()
                    .postId(postId)
                    .userId(userId)
                    .build();
            postLikeMapper.insert(like);
            isLiked = true;
            likeCountIncrement = 1;
        }

        // 4. 更新帖子点赞数（使用缓存）
        Long newLikeCount = countCacheService.incrementPostLikeCount(postId, likeCountIncrement);

        // 5. 返回结果
        LikeToggleRespVO result = new LikeToggleRespVO();
        result.setIsLiked(isLiked);
        result.setLikeCount(newLikeCount.intValue());
        return result;
    }

    @Override
    public void incrementViewCount(Long postId) {
        postMapper.updateViewCount(postId);
    }

    /**
     * 校验帖子是否存在
     */
    private CommunityPostDO validatePostExists(Long id) {
        CommunityPostDO post = postMapper.selectById(id);
        if (post == null) {
            throw exception(COMMUNITY_POST_NOT_EXISTS);
        }
        return post;
    }

}
